#ifndef ZRTSP_CLIENT_H_
#define ZRTSP_CLIENT_H_

#include <memory>
#include <string>
#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"
#include "zRtspClientApis.h"

class ZRtspClient {
	friend void TaskShutdownStream(void* arg);
class StreamClientState{
public:
	StreamClientState(bool connTcp) 
		: iter(NULL),
		session(NULL),
		subsession(NULL),
		streamTimerTask(NULL),
		duration(0.0),
		connTcp_(connTcp)
	{ }

	~StreamClientState()
	{
		delete iter;
		if (session != NULL) {
			// We also need to delete "session", and unschedule "streamTimerTask" (if set)
			UsageEnvironment& env = session->envir(); // alias
			env.taskScheduler().unscheduleDelayedTask(streamTimerTask);
			Medium::close(session);
		}
	}

public:
	MediaSubsessionIterator* iter;
	MediaSession* session;
	MediaSubsession* subsession;
	TaskToken streamTimerTask;
	double duration;
	bool connTcp_;//true TCP, false UDP
};

class ourRTSPClient : public RTSPClient {
public:
	ourRTSPClient(UsageEnvironment& env, char const* rtspURL, int handle, ZRtspCallBack cb,
		int verbosityLevel, char const* applicationName, portNumBits tunnelOverHTTPPortNum, bool connTcp, int cacheBuffSize)
		: RTSPClient(env, rtspURL, verbosityLevel, applicationName, tunnelOverHTTPPortNum, -1),
		scs(connTcp),
		handle_(handle),
		cb_(cb),
		cacheBuffSize_(cacheBuffSize)
	{  }

	virtual ~ourRTSPClient(){  }
	StreamClientState scs;
	int handle_;
	ZRtspCallBack cb_;
	int cacheBuffSize_;
};



public:
	explicit ZRtspClient(const char *url,
							int connType,
							const char* user,
							const char* pwd) 
		:connType_(connType),
		rtspUrl_(url),
		user_(user),
		pwd_(pwd),
		pRtspClient_(nullptr)
	{	}
		
	~ZRtspClient() {
		if (pRtspClient_) { delete pRtspClient_; pRtspClient_ = nullptr; }
	}

	int Connect(UsageEnvironment& env, int handle, ZRtspCallBack cb, int cacheBuffSize);
	int DisConnect(int handle);

private:
	static void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString);
	static void setupNextSubsession(RTSPClient* rtspClient, bool useTcp);
	static void continueAfterSETUP(RTSPClient* rtspClient, int resultCode, char* resultString);
	static void continueAfterPLAY(RTSPClient* rtspClient, int resultCode, char* resultString);
	static void subsessionAfterPlaying(void* clientData);
	static void subsessionByeHandler(void* clientData, char const* reason);
	static void shutdownStream(RTSPClient* rtspClient, int exitCode = 1);

private:
	int connType_;
	std::string rtspUrl_;
	std::string user_;
	std::string pwd_;
	ourRTSPClient* pRtspClient_;
};


#endif // !ZRTSP_CLIENT_H_

